package me.demo.sprite4m;

import java.awt.AWTException;
import java.awt.MenuItem;
import java.awt.Point;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import javax.imageio.ImageIO;
import javax.swing.SwingUtilities;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.sun.jna.Platform;

import me.demo.sprite4m.config.Configuration;
import me.demo.sprite4m.config.Entry;
import me.demo.sprite4m.exception.BehaviorInstantiationException;
import me.demo.sprite4m.exception.CantBeAliveException;
import me.demo.sprite4m.exception.ConfigurationException;

/**
 * 
 */
public class Main {

    private static final Logger log = Logger.getLogger(Main.class.getName());

    static final String BEHAVIOR_GATHER = "集中在鼠标周围";

    static {
        try {
            LogManager.getLogManager().readConfiguration(Main.class.getResourceAsStream("/logging.properties"));
        } catch (final SecurityException e) {
            e.printStackTrace();
        } catch (final IOException e) {
            e.printStackTrace();
        }
    }

    private static Main instance = new Main();

    public static Main getInstance() {
        return instance;
    }

    private final Manager manager = new Manager();

    private final Configuration configuration = new Configuration();

    public static void main(final String[] args) {

        getInstance().run();
    }

    public void run() {

        // 加载配置
        loadConfiguration();

        // 创建托盘图标
        createTrayIcon();

        // 创建一直精灵
        createMascot();

        getManager().start();
    }

    /**
     * 加载配置
     */
    private void loadConfiguration() {

        try {
            log.log(Level.INFO, "加载配置文件({0})", "conf/動作.xml");
            
            final Document actions = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                    .parse(getConfAsStream("動作.xml"));

            log.log(Level.INFO, "加载配置文件({0})", "conf/行動.xml");

            this.getConfiguration().load(new Entry(actions.getDocumentElement()));

            final Document behaviors = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                    .parse(getConfAsStream("行動.xml"));

            this.getConfiguration().load(new Entry(behaviors.getDocumentElement()));

            this.getConfiguration().validate();

        } catch (final IOException e) {
            log.log(Level.SEVERE, "加载配置文件失败", e);
            exit();
        } catch (final SAXException e) {
            log.log(Level.SEVERE, "加载配置文件失败", e);
            exit();
        } catch (final ParserConfigurationException e) {
            log.log(Level.SEVERE, "加载配置文件失败", e);
            exit();
        } catch (final ConfigurationException e) {
            log.log(Level.SEVERE, "配置文件描述有误", e);
            exit();
        }
    }
    
    private InputStream getConfAsStream(String conf){
        return Main.class.getClassLoader().getResourceAsStream("conf/"+conf);
    }

    /**
     * 创建托盘图标.
     * 
     * @throws AWTException
     * @throws IOException
     */
    private void createTrayIcon() {

        log.log(Level.INFO, "创建托盘图标");

        if (SystemTray.getSystemTray() == null) {
            return;
        }

        // "增加"菜单项
        final MenuItem increaseMenu = new MenuItem("增加");
        increaseMenu.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent event) {
                createMascot();
            }
        });

        // "集合！"菜单项
        final MenuItem gatherMenu = new MenuItem("集合！");
        gatherMenu.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent event) {
                gatherAll();
            }
        });

        // "只留下一只"菜单项
        final MenuItem oneMenu = new MenuItem("只留下一只");
        oneMenu.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent event) {
                remainOne();
            }
        });

        // "撤消窗口"菜单项
        final MenuItem restoreMenu = new MenuItem(Platform.isMac() ? "撤消窗口" : "撤消IE");
        restoreMenu.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent event) {
                restoreIE();
            }
        });

        // "关闭"菜单项
        final MenuItem closeMenu = new MenuItem("关闭");
        closeMenu.addActionListener(new ActionListener() {
            public void actionPerformed(final ActionEvent e) {
                exit();
            }
        });

        // 创建弹出菜单
        final PopupMenu trayPopup = new PopupMenu();
        trayPopup.add(increaseMenu);
        trayPopup.add(gatherMenu);
        trayPopup.add(oneMenu);
        trayPopup.add(restoreMenu);
        trayPopup.add(new MenuItem("-"));
        trayPopup.add(closeMenu);

        /*
         * // set dock menu if (Platform.isMac()) { // ポップアップメニューを作成 final
         * PopupMenu dockMenu = new PopupMenu();
         * 
         * final Application application = Application.getApplication(); Image
         * dockIcon =
         * Toolkit.getDefaultToolkit().getImage(getClass().getClassLoader().
         * getResource("icon.png")); application.setDockIconImage(dockIcon);
         * application.setDockMenu(dockMenu); }
         */

        try {
            // 创建托盘图标
            final TrayIcon icon = new TrayIcon(ImageIO.read(Main.class.getClassLoader().getResource("img/icon.png")), "しめじ", trayPopup);

            // 图标左键点击时“增加”
            // 但Mac因为用左单击菜单打开了，
            // 右键点击增殖
            icon.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(final MouseEvent e) {
                    if (!Platform.isMac() && SwingUtilities.isLeftMouseButton(e)
                            || Platform.isMac() && SwingUtilities.isRightMouseButton(e)) {
                        createMascot();
                    }
                }
            });

            // 显示托盘图标 
            SystemTray.getSystemTray().add(icon);

        } catch (final IOException e) {
            log.log(Level.SEVERE, "创建托盘图标失败", e);
            exit();

        } catch (final AWTException e) {
            log.log(Level.SEVERE, "创建托盘图标失败", e);
            MascotEventHandler.setShowSystemTrayMenu(true);
            getManager().setExitOnLastRemoved(true);
        }

    }

    /**
     * しめじを一匹作成する.
     */
    public void createMascot() {

        log.log(Level.INFO, "マスコットを作成");

        // マスコットを1個作成
        final Mascot mascot = new Mascot();

        // 範囲外から開始
        mascot.setAnchor(new Point(-1000, -1000));
        // ランダムな向きで
        mascot.setLookRight(Math.random() < 0.5);

        try {
            mascot.setBehavior(getConfiguration().buildBehavior(null, mascot));

            this.getManager().add(mascot);

        } catch (final BehaviorInstantiationException e) {
            log.log(Level.SEVERE, "最初の行動の初期化に失敗しました", e);
            mascot.dispose();
        } catch (final CantBeAliveException e) {
            log.log(Level.SEVERE, "生き続けることが出来ない状況", e);
            mascot.dispose();
        }

    }

    public void gatherAll() {
        Main.this.getManager().setBehaviorAll(Main.this.getConfiguration(), BEHAVIOR_GATHER);
    }

    public void remainOne() {
        Main.this.getManager().remainOne();
    }

    public void restoreIE() {
        NativeFactory.getInstance().getEnvironment().restoreIE();
    }

    public void exit() {

        this.getManager().disposeAll();
        this.getManager().stop();

        System.exit(0);
    }

    public Configuration getConfiguration() {
        return this.configuration;
    }

    private Manager getManager() {
        return this.manager;
    }

}
